package com.edfu.core.testmgt.service.ws;

import java.util.List;
import java.util.Set;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.edfu.core.identitymgt.vo.User;
import com.edfu.core.testmgt.service.api.ITestMgtService;
import com.edfu.core.testmgt.vo.FormatType;
import com.edfu.core.testmgt.vo.Option;
import com.edfu.core.testmgt.vo.Question;
import com.edfu.core.testmgt.vo.QuestionType;
import com.edfu.core.testmgt.vo.Test;
import com.edfu.core.testmgt.vo.TestBundle;
import com.edfu.core.testmgt.vo.TestType;
import com.edfu.core.testmgt.vo.UserTest;

@Path("/")
@Produces( { MediaType.APPLICATION_JSON })
@Consumes(MediaType.APPLICATION_JSON)
@WebService(targetNamespace = "http://com.edfu.core.testmgt.service.ws.TestMgtService")
public class TestMgtServiceDelegate {
	
	private static Logger logger = LoggerFactory.getLogger(TestMgtServiceDelegate.class);
	
	@Autowired
	private ITestMgtService testMgtService;
	
	@POST
	@Path("/tests")
	@WebMethod(operationName = "createTest")
	public Response createTest(Test test) {
		Test createdTest = testMgtService.createTest(0, test);
		logger.debug("Test creation successful");
		
		return Response.ok(createdTest).build();
	}

	@POST
	@Path("/tests/testBundleId/{testBundleId}")
	@WebMethod(operationName = "createTestInTestBundle")
	public Response createTest(@PathParam(value = "testBundleId") long testBundleId, Test test) {
		Test createdTest = testMgtService.createTest(testBundleId, test);
		logger.debug("Test creation successful");
		
		return Response.ok(createdTest).build();
	}

	@PUT
	@Path("/tests")
	@WebMethod(operationName = "updateTest")
	public Response updateTest(Test test) {
		Test updatedTest = testMgtService.updateTest(test);
		logger.debug("Test updation is successful");
		
		return Response.ok(updatedTest).build();
	}

	@DELETE
	@Path("/tests/{testId}")
	@WebMethod(operationName = "removeTest")
	public Response removeTest(@PathParam(value = "testId") Integer testId) {
		testMgtService.removeTest(testId);
		logger.debug("Test is removed successfully");
		
		return Response.ok().build();
	}

	@GET
	@Path("/tests/{testId}")
	@WebMethod(operationName = "getTest")
	public Test getTest(@PathParam(value = "testId") Integer testId) {
		return testMgtService.getTest(testId);
	}

	@POST
	@Path("/testbundles")
	@WebMethod(operationName = "createTestBundle")
	public Response createTestBundle(TestBundle testBundle) {
		TestBundle createdTestBundle = testMgtService.createTestBundle(testBundle);
		logger.debug("Test Bundle is created successfully");
			
		return Response.ok(createdTestBundle).build();
	}

	@PUT
	@Path("/testbundles")
	@WebMethod(operationName = "updateTestBundle")
	public Response updateTestBundle(TestBundle testBundle) {
		TestBundle updatedBundle = testMgtService.updateTestBundle(testBundle);
		logger.debug("Test Bundle updated successfully");
		
		return Response.ok(updatedBundle).build();	
	}

	@DELETE
	@Path("/testbundles/{testBundleId}")
	@WebMethod(operationName = "removeTestBundle")
	public Response removeTestBundle(@PathParam(value = "testBundleId") Integer testBundleId) {
		testMgtService.removeTestBundle(testBundleId);
		logger.debug("Test Bundle is removed successfully");
		
		return Response.ok().build();
	}

	@GET
	@Path("/testbundles/{testBundleId}")
	@Produces(MediaType.APPLICATION_XML)
	@WebMethod(operationName = "getTestBundle")
	public TestBundle getTestBundle(@PathParam(value = "testBundleId") Integer testBundleId) {
		return testMgtService.getTestBundle(testBundleId);
	}

	@GET
	@Path("/tests/testbundles/{testBundleId}")
	@WebMethod(operationName = "getTests")
	public List<Test> getTests(@PathParam(value = "testBundleId") Integer testBundleId) {
		return testMgtService.getTests(testBundleId);
	}

	@POST
	@Path("/testTypes")
	@WebMethod(operationName = "createTestType")
	public Response createTestType(TestType testType) {
		TestType tt = testMgtService.createTestType(testType.getName(), testType.getDesc());
		logger.debug("Test Type is created successfully");
		
		return Response.ok(tt).build();
	}

	@PUT
	@Path("/testTypes")
	@WebMethod(operationName = "updateTestType")
	public Response updateTestType(TestType testType) {
		TestType tt = testMgtService.updateTestType(testType);
		logger.debug("Test Type is updated successfully");
		
		return Response.ok(tt).build();
	}

	@DELETE
	@Path("/testTypes/{testTypeId}")
	@WebMethod(operationName = "removeTestType")
	public Response removeTestType(@PathParam(value = "testTypeId") Integer testTypeId) {
		testMgtService.removeTestType(testTypeId);
		logger.debug("Test Type is removed successfully");
		
		return Response.ok().build();
	}

	@GET
	@Path("/testTypes")
	@WebMethod(operationName = "getTestTypes")
	public List<TestType> getTestTypes() {
		return testMgtService.getTestTypes();
	}

	@GET
	@Path("/testTypes/{testTypeId}")
	@WebMethod(operationName = "getTestType")
	public TestType getTestType(@PathParam(value = "testTypeId") Integer testTypeId) {
		return testMgtService.getTestType(testTypeId);
	}
	
	@POST
	@Path("/formatTypes/{formatTypeName}")
	@WebMethod(operationName = "createFormatType")
	public Response createFormatType(@PathParam(value = "formatTypeName") String formatTypeName) {
		FormatType ft = testMgtService.createFormatType(formatTypeName);
		logger.debug("Format Type is created successfully");
		
		return Response.ok(ft).build();
	}

	@PUT
	@Path("/formatTypes")
	@WebMethod(operationName = "updateFormatType")
	public Response updateFormatType(FormatType formatType) {
		FormatType ft = testMgtService.updateFormatType(formatType);
		logger.debug("Format Type is updated successfully");
		
		return Response.ok(ft).build();
	}

	@DELETE
	@Path("/formatTypes/{formatTypeId}")
	@WebMethod(operationName = "removeFormatType")
	public Response removeFormatType(@PathParam(value = "formatTypeId") Integer formatTypeId) {
		testMgtService.removeFormatType(formatTypeId);
		logger.debug("Format Type is removed successfully");
		
		return Response.ok().build();
	}

	@GET
	@Path("/formatTypes")
	@WebMethod(operationName = "getFormatTypes")
	public List<FormatType> getFormatTypes() {
		return testMgtService.getFormatTypes();
	}

	@GET
	@Path("/formatTypes/{formatTypeId}")
	@WebMethod(operationName = "getFormatType")
	public FormatType getFormatType(@PathParam(value = "formatTypeId") Integer formatTypeId) {
		return testMgtService.getFormatType(formatTypeId);
	}	

	@POST
	@Path("/tests/{testId}/questions")
	@WebMethod(operationName = "addQuestion")
	public Response addQuestion(@PathParam(value = "testId") Integer testId, Question question) {
		Question qu = testMgtService.addQuestion(testId, question);
		logger.debug("Question is added successfully");
		
		return Response.ok(qu).build();
	}

	@POST
	@Path("/tests/{testId}/questionsList")
	@WebMethod(operationName = "addQuestions")
	public Response addQuestions(@PathParam(value = "testId") Integer testId, Set<Question> questions) {
		testMgtService.addQuestions(testId, questions);
		logger.debug("Questions are added successfully");
		
		return Response.ok().build();
	}

	@PUT
	@Path("/tests/questions")
	@WebMethod(operationName = "updateQuestion")
	public Response updateQuestion(Question question) {
		Question qu = testMgtService.updateQuestion(question);
		logger.debug("Question is updated successfully");
		
		return Response.ok(qu).build();
	}

	@DELETE
	@Path("/tests/questions/{questionId}")
	@WebMethod(operationName = "removeQuestion")
	public Response removeQuestion(@PathParam(value = "questionId") Integer questionId) {
		testMgtService.removeQuestion(questionId);
		logger.debug("Question has been removed successfully");
		
		return Response.ok().build();
	}

	@GET
	@Path("/tests/{testId}/questions")
	@WebMethod(operationName = "getQuestions")
	public Set<Question> getQuestions(@PathParam(value = "testId") Integer testId) {
		return testMgtService.getQuestions(testId);
	}

	@GET
	@Path("/tests/questions/{questionId}")
	@WebMethod(operationName = "getAnswers")
	public Set<Option> getAnswers(@PathParam(value = "questionId") Integer questionId) {
		return testMgtService.getAnswers(questionId);		
	}

	@POST
	@Path("/questionTypes")
	@WebMethod(operationName = "createQuestionType")
	public Response createQuestionType(QuestionType questionType) {
		QuestionType qt = testMgtService.createQuestionType(questionType.getName(), questionType.getDesc());
		
		return Response.ok(qt).build();
	}

	@PUT
	@Path("/questionTypes")
	@WebMethod(operationName = "updateQuestionType")
	public Response updateQuestionType(QuestionType questionType) {
		QuestionType qt = testMgtService.updateQuestionType(questionType);
		logger.debug("Question Type is updated successfully");
		
		return Response.ok(qt).build();
	}

	@DELETE
	@Path("/questionTypes/{questionTypeId}")
	@WebMethod(operationName = "removeQuestionType")
	public Response removeQuestionType(@PathParam(value = "questionTypeId") Integer questionTypeId) {
		testMgtService.removeQuestionType(questionTypeId);
		logger.debug("Question Type has been removed successfully");
		
		return Response.ok().build();
	}

	@GET
	@Path("/questionTypes")
	@WebMethod(operationName = "getQuestionTypes")
	public List<QuestionType> getQuestionTypes() {
		return testMgtService.getQuestionTypes();
	}

	@GET
	@Path("/questionTypes/{questionTypeId}")
	@WebMethod(operationName = "getQuestionType")
	public QuestionType getQuestionType(@PathParam(value = "questionTypeId") Integer questionTypeId) {
		return testMgtService.getQuestionType(questionTypeId);
	}

	@POST
	@Path("/tests/{testId}/users/{userId}/subscribe")
	@WebMethod(operationName = "subscribeTest")
	public Response subscribeTest(@PathParam(value = "testId") Integer testId, @PathParam(value = "userId") String userId) {
		Test test = new Test();
		test.setId(testId);
		
		User user = new User();
		user.setUserId(userId);
		
		UserTest userTest = new UserTest();
		userTest.setTest(test);
		userTest.setUser(user);
		
		testMgtService.subscribeTest(userTest);
		
		return Response.ok().build();
	}

	@POST
	@Path("/tests/{testId}/users/{userId}/unsubscribe")
	@WebMethod(operationName = "unsubscribeTest")
	public Response unsubscribeTest(@PathParam(value = "testId") Integer testId, @PathParam(value = "userId") String userId) {
		Test test = new Test();
		test.setId(testId);
		
		User user = new User();
		user.setUserId(userId);
		
		UserTest userTest = new UserTest();
		userTest.setTest(test);
		userTest.setUser(user);
		
		testMgtService.unsubscribeTest(userTest);
				
		return Response.ok().build();
	}

	@POST
	@Path("/tests/userDetails")
	@WebMethod(operationName = "addOrUpdateUserTestDetails")
	public Response addOrUpdateUserTestDetails(UserTest userTest) {
		testMgtService.addOrUpdateUserTestDetails(userTest);
				
		return Response.ok().build();
	}

	@GET
	@Path("/tests/{testId}/users/{userId}")
	@WebMethod(operationName = "getUserTestDetails")
	public UserTest getUserTestDetails(@PathParam(value = "testId") Integer testId, @PathParam(value = "userId") String userId) {
		Test test = new Test();
		test.setId(testId);
		
		User user = new User();
		user.setUserId(userId);
		
		UserTest userTest = new UserTest();
		userTest.setTest(test);
		userTest.setUser(user);
		
		return testMgtService.getUserTestDetails(userTest);
	}

	@GET
	@Path("/tests/{testId}/questionsWithAnswers")
	@WebMethod(operationName = "getQuestionsWithAnswers")
	public Set<Question> getQuestionsWithAnswers(@PathParam(value = "testId") Integer testId) {
		return testMgtService.getQuestionsWithAnswers(testId);		
	}

	@GET
	@Path("/tests/{testId}/users/{userId}/answers")
	@WebMethod(operationName = "getUserTestDetailsWithAnswers")
	public UserTest getUserTestDetailsWithAnswers(@PathParam(value = "testId") Integer testId, @PathParam(value = "userId") String userId) {
		Test test = new Test();
		test.setId(testId);
		
		User user = new User();
		user.setUserId(userId);
		
		UserTest userTest = new UserTest();
		userTest.setTest(test);
		userTest.setUser(user);
		
		return testMgtService.getUserTestDetailsWithAnswers(userTest);		
	}

	@POST
	@Path("/tests/{testId}/users/{userId}")
	@WebMethod(operationName = "submitUserTestAnswers")
	public Response submitUserTestAnswers(@PathParam(value = "testId") Integer testId, @PathParam(value = "userId") String userId) {
		Test test = new Test();
		test.setId(testId);
		
		User user = new User();
		user.setUserId(userId);
		
		UserTest userTest = new UserTest();
		userTest.setTest(test);
		userTest.setUser(user);
		
		testMgtService.submitUserTestAnswers(userTest);
		
		return Response.ok().build();
	}
	
	@GET
	@Path("/tests")
	@WebMethod(operationName = "getTestDetails")
	public List<Test> getTestDetails() {
		return testMgtService.getTestDetails();
	}
	
	@GET
	@Path("/tests/testCategories/{categoryName}")
	@WebMethod(operationName = "getTestDetailsForCategory")
	public List<Test> getTestDetails(@PathParam(value = "categoryName") String categoryName) {
		return testMgtService.getAssociatedTests(categoryName);
	}
	
	@GET
	@Path("/tests/users/{userId}")
	@WebMethod(operationName = "getSubscribedTests")
	public List<Test> getSubscribedTests(@PathParam(value = "userId") String userId) {
		return testMgtService.getSubscribedTests(userId);
	}

}
